﻿package bdz.common.managers
{
	import bdz.common.events.NetStreamManagerEvent;
	
	import flash.events.*;
	import flash.media.SoundTransform;
	import flash.media.Video;
	import flash.net.NetConnection;
	import flash.net.NetStream;
	import flash.utils.*;
	
	/**
	 * ...
	 * @author ...
	 */
	public class NetStreamManager extends EventDispatcher
	{
		protected var _ns:NetStream;
		protected var _nc:NetConnection;
		protected var _source:String;
		protected var _nsduration:Number;
		protected var _progressive:Boolean = true;
		protected var _streampreload:Number;
		protected var _playprogress:Number;
		protected var _autoplay:Boolean = false;
		protected var _meta:Object;
		protected var _vidSource:Video;
		protected var _defvolume:Number = 1;
		public var loadOffset:Number = 0;
		public var refreshRate:Number = 100;
		public var bufferTime:Number = 3;
		protected var _started:Boolean = false;
		protected var _playing:Boolean = false;
		public var paused:Boolean;
		function NetStreamManagerNetStreamManager() {
			
		}
		protected function initialize():void {
			
			clear()
			
			if(_source && _source != "null" && _source != "undefined"){
				_nc = new NetConnection();
				//progressive connection
				_nc.connect(null);
				_ns = new NetStream(_nc);
				_ns.client = this;
				_ns.play(_source);
				_ns.bufferTime = bufferTime;
				_ns.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);
				_ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncError);
				
				if (!_autoplay) {
					_ns.pause();
					paused = true;
				}else {
					clearInterval(_playprogress);
					_playprogress = setInterval(onPlayProgress, refreshRate);
				}
				if (_vidSource) {
					_vidSource.attachNetStream(_ns);
				}
				
				clearInterval(_streampreload);
				_streampreload = setInterval(onLoadProgress, refreshRate);
				_playing = _autoplay;
			}
		}
		public function onXMPData(d:* = null):void{
			
		}
		protected function checkPlayCompletion():void {
			if (_ns.time >= _nsduration) {
				clearInterval(_playprogress);
				dispatchEvent(new NetStreamManagerEvent(NetStreamManagerEvent.PLAY_COMPLETE));
			}
		}
		protected function onLoadProgress():void {
			
			var pct:Number = _ns.bytesLoaded / _ns.bytesTotal;
			pct += loadOffset;
			if (pct < 1) {
				if (pct < 0) {
					pct = 0;
				}
				dispatchEvent(new NetStreamManagerEvent(NetStreamManagerEvent.LOAD_PROGRESS, { percent:pct, loaded:_ns.bytesLoaded, total:_ns.bytesTotal }))
			}else {
				clearInterval(_streampreload);
				dispatchEvent(new NetStreamManagerEvent(NetStreamManagerEvent.LOAD_COMPLETE, { percent:1 } ));
			}
		}
		protected function onPlayProgress():void {
			checkPlayCompletion();
			var pct:Number = _ns.time / _nsduration;
			if (pct < 0) {
				pct = 0;
			}
			_playing = true;
			dispatchEvent(new NetStreamManagerEvent(NetStreamManagerEvent.PLAY_PROGRESS, { total:_nsduration, percent:pct, position:_ns.time } ));
			
			
		}
		
		public function onMetaData(info:Object):void {
			
			_meta = info;
			_nsduration = info.duration;
			
			dispatchEvent(new NetStreamManagerEvent(NetStreamManagerEvent.META_DATA, info));
		}
		public function onAsyncError(evt:AsyncErrorEvent):void {
			
		}
		public function onNetStatus(evt:NetStatusEvent):void {
			
			if (evt.info.code == "NetStream.Seek.Notify" ||
				evt.info.code == "NetStream.Play.Start"
				) {
				dispatchEvent(new NetStreamManagerEvent(NetStreamManagerEvent.BUFFERING, evt.info));
			}
			if (evt.info.code == "NetStream.Buffer.Full" || evt.info.code == "NetStream.Play.Stop") {
				dispatchEvent(new NetStreamManagerEvent(NetStreamManagerEvent.BUFFER_FULL, evt.info));
			}
			if (evt.info.code == "NetStream.Play.Start" && _playing) {
				
				if (!_started) {
					_started = true;
					dispatchEvent(new NetStreamManagerEvent(NetStreamManagerEvent.PLAY_STARTED, evt.info));
				}
			}
			if (evt.info.code == "NetStream.Play.Complete") {
				_started = false;
				dispatchEvent(new NetStreamManagerEvent(NetStreamManagerEvent.PLAY_COMPLETE, evt.info));
			}
			dispatchEvent(new NetStreamManagerEvent(NetStreamManagerEvent.STATUS, evt.info));
		}
		public function onPlayStatus(info:Object):void {
			
			if (info.info.code == "NetStream.Play.Complete") {
				dispatchEvent(new NetStreamManagerEvent(NetStreamManagerEvent.PLAY_COMPLETE, info));
			}
		}
		public function onCuePoint(info:Object):void {
			dispatchEvent(new NetStreamManagerEvent(NetStreamManagerEvent.ON_CUEPOINT, info));
		}
		/**
		 * PUBLIC FUNCTIONS
		 */
		public function clear():void {
			_started = false;
			try {
				clearInterval(_playprogress);
				clearInterval(_streampreload);
				_ns.close();
				_nc.close();
				_ns = null;
				_nc = null;
				
			}catch (e:Error) {
				
			}
		}
		public function play():void {
			try {
				
				var _trans:SoundTransform = new SoundTransform(_defvolume);
				_ns.soundTransform = _trans;
				if (Math.ceil(_ns.time) == Math.ceil(_nsduration)) {
					_ns.seek(0);
				}else {
					_ns.resume();
				}
				clearInterval(_playprogress);
				_playprogress = setInterval(onPlayProgress, refreshRate);
				paused = false;
			}catch (e:Error) {
				
			}
		}
		public function seek(t:Number):void {
			try{
				_ns.seek(t);
			}catch (e:Error) {
				
			}
		}
		public function pause():void {
			try{
				_ns.pause();
				paused = true;
			}catch(e:Error){}
			clearInterval(_playprogress);
		}
		public function rewind():void {
			try{
				_ns.seek(0);			
				clearInterval(_playprogress);
				_playprogress = setInterval(onPlayProgress, refreshRate);
			}catch(e:Error){}
		}
		/**
		 * ACCESSORS
		 */
		public function set volume(vol:Number):void {
			
			_defvolume = vol;
			var _trans:SoundTransform = new SoundTransform(_defvolume);
			try {
				_ns.soundTransform = _trans;
			}catch (e:Error) { }
			
		}
		public function get volume():Number {
			return _defvolume;
		}
		public function set autoPlay(b:Boolean):void {
			_autoplay = b;
		}
		public function get autoPlay():Boolean {
			return _autoplay;
		}
		public function get meta():Object {
			return _meta;
		}
		public function get stream():NetStream {
			return _ns;
		}
		public function get connection():NetConnection {
			return _nc;
		}
		public function set source(str:String):void {
			
			_source = str;
			initialize();
			
		}
		public function get source():String {
			return _source;
		}
		public function set vsource(v:Video):void {
			_vidSource = v;
		}
		public function get vsource():Video {
			return _vidSource;
		}
		public function get isPlaying():Boolean{
			return _playing;
		}
		
	}
	
}